#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/callback.h>
#include "cil_stub.h"
#include "cil_type.h"
#include "cil_stub.h"
#include "cil_wrap.h"


#define wrap_out OCaml_stdout_wrap()
#define DOC_WIDTH 100

/**
* Ocaml
*/
inline OCamlOutChannel wrap_out {
  return OCaml_stdout(Val_unit);
}

inline OCamlOutChannel OCaml_open_out_wrap(char* filename) {
	return OCaml_open_out(caml_copy_string(filename));
}

inline void OCaml_flush_wrap() {
  OCaml_flush(wrap_out);
}




/**
* module Pretty
*/
inline PrettyDoc Pretty_nil_wrap() {
  return Pretty_nil(Val_unit);
}

inline void Pretty_fprint_wrap(PrettyDoc doc) {
  Pretty_fprint(wrap_out, 100, doc);
}



/**
* module Cil
*/
inline CilFile Frontc_parse_wrap(const char* filename) {
  return Frontc_parse(caml_copy_string(filename), Val_unit);
}

inline CilPrinter Cil_defaultCilPrinter_wrap() {
  Cil_defaultCilPrinter(Val_unit);
}

inline void Cil_dumpFile_wrap(CilFile file) {
  Cil_dumpFile(Cil_defaultCilPrinter_wrap(), wrap_out, caml_copy_string("/tmp/cil.log"), file);
  OCaml_flush_wrap();
}

inline void Cil_dumpGlobal_wrap(CilGlobal global) {
  Cil_dumpGlobal(Cil_defaultCilPrinter_wrap(), wrap_out, global);
  OCaml_flush_wrap();
}

inline void Cil_dumpInit_wrap(CilInit init) {
  Cil_dumpInit(Cil_defaultCilPrinter_wrap(), wrap_out, Val_int(0), init);
  OCaml_flush_wrap();
}

inline void Cil_dumpBlock_wrap(CilBlock block) {
  Cil_dumpBlock(Cil_defaultCilPrinter_wrap(), wrap_out, Val_int(0), block);
  OCaml_flush_wrap();
}
  
inline void Cil_dumpStmt_wrap(CilStmt stmt) {
  Cil_dumpStmt(Cil_defaultCilPrinter_wrap(), wrap_out, Val_int(0), stmt); 
  OCaml_flush_wrap();
}
  

  
inline void Cil_d_type_wrap(CilTyp typ) {
  Pretty_fprint_wrap(Cil_d_type(Val_unit, typ));
  OCaml_flush_wrap();
}
  
inline void Cil_d_exp_wrap(CilExp exp)	{
  Pretty_fprint_wrap(Cil_d_exp(Val_unit, exp)); 
  OCaml_flush_wrap();
}
  
inline void Cil_d_lval_wrap(CilLval lval) {
  Pretty_fprint_wrap(Cil_d_lval(Val_unit, lval)); 
  OCaml_flush_wrap();
}
  
inline void Cil_d_offset_wrap(CilOffset offset)	{
  Pretty_fprint_wrap(Cil_d_offset(Pretty_nil_wrap() , Val_unit, offset)); 
  OCaml_flush_wrap();
}

inline void Cil_d_init_wrap(CilInit init)	{
  Pretty_fprint_wrap(Cil_d_init(Val_unit, init)); 
  OCaml_flush_wrap();
}
inline void Cil_d_binop_wrap(CilBinop binop)	{
  Pretty_fprint_wrap(Cil_d_binop(Val_unit, binop)); 
  OCaml_flush_wrap();
}
  
inline void Cil_d_unop_wrap(CilUnop unop)	{
  Pretty_fprint_wrap(Cil_d_unop(Val_unit, unop));
  OCaml_flush_wrap();
}
  
inline void Cil_d_attr_wrap(CilAttribute attr)	{
  Pretty_fprint_wrap(Cil_d_attr(Val_unit, attr));
  OCaml_flush_wrap();
}
    
inline void Cil_d_attrparam_wrap(CilAttrparam attrparam)	{
  Pretty_fprint_wrap(Cil_d_attrparam(Val_unit, attrparam));
  OCaml_flush_wrap();
}
  
inline void Cil_d_attrlist_wrap(OCamlList attrlist)	{
  Pretty_fprint_wrap(Cil_d_attrlist(Val_unit, attrlist));
  OCaml_flush_wrap();
}
  
inline void Cil_d_instr_wrap(CilInstr instr)	{
  Pretty_fprint_wrap(Cil_d_instr(Val_unit, instr)); 
  OCaml_flush_wrap();
}
 
inline void Cil_d_label_wrap(CilLabel label)	{
  Pretty_fprint_wrap(Cil_d_label(Val_unit, label));
  OCaml_flush_wrap();
}
 
inline void Cil_d_stmt_wrap(CilStmt stmt) {
  Pretty_fprint_wrap(Cil_d_stmt(Val_unit, stmt));
  OCaml_flush_wrap();
}

inline void Cil_d_block_wrap(CilBlock block)	{
  Pretty_fprint_wrap(Cil_d_block(Val_unit, block));
  OCaml_flush_wrap();
}
    
inline void Cil_d_global_wrap(CilGlobal global) {
  Pretty_fprint_wrap(Cil_d_global(Val_unit, global));
  OCaml_flush_wrap();
}
  
inline void Cil_d_shortglobal_wrap(CilGlobal global) {
  Pretty_fprint_wrap(Cil_d_shortglobal(Val_unit, global));
  OCaml_flush_wrap();
}
  
inline void Cil_dn_type_wrap(CilTyp typ)	{
  Pretty_fprint_wrap(Cil_dn_type(Val_unit, typ));
  OCaml_flush_wrap();
}
   
inline void Cil_dn_exp_wrap(CilExp exp) {
  Pretty_fprint_wrap(Cil_dn_type(Val_unit, exp)); 
  OCaml_flush_wrap();
}

inline void Cil_dn_lval_wrap(CilLval lval) {
  Pretty_fprint_wrap(Cil_dn_lval(Val_unit, lval));
  OCaml_flush_wrap();
}
 
inline void Cil_dn_init_wrap(CilInit init) {
  Pretty_fprint_wrap(Cil_dn_init(Val_unit, init));
  OCaml_flush_wrap();
}
   
inline void Cil_dn_attr_wrap(CilAttribute attr) {
  Pretty_fprint_wrap(Cil_dn_attr(Val_unit, attr));
  OCaml_flush_wrap();
}

inline void Cil_dn_attrparam_wrap(CilAttrparam attrparam) {
  Pretty_fprint_wrap(Cil_dn_attrparam(Val_unit, attrparam)); 
  OCaml_flush_wrap();
}
  

inline void Cil_dn_attrlist_wrap(OCamlList attrlist) {
  Pretty_fprint_wrap(Cil_dn_attrlist(Val_unit, attrlist)); 
  OCaml_flush_wrap();
}
  

inline void Cil_dn_instr_wrap(CilInstr instr) {
  Pretty_fprint_wrap(Cil_dn_instr(Val_unit, instr));
  OCaml_flush_wrap();
}
    
inline void Cil_dn_stmt_wrap(CilStmt stmt) {
  Pretty_fprint_wrap(Cil_dn_stmt(Val_unit, stmt)); 
  OCaml_flush_wrap();
}
     
inline void Cil_dn_global_wrap(CilGlobal global) {
  Pretty_fprint_wrap(Cil_dn_global(Val_unit, global));
  OCaml_flush_wrap();
}
  

/**
* module Cfg
*/

inline void Cfg_printCfgChannel_wrap(CilFundec fundec) {
  Cfg_printCfgChannel(wrap_out, fundec);
  OCaml_flush_wrap();
}

inline int Cfg_start_id_wrap() {
  return Int_val(DEREF(Cfg_start_id(Val_unit)));
}

inline OCamlList Cfg_nodeList_wrap() {
  return DEREF(Cfg_nodeList(Val_unit));
}

inline int Cfg_numNodes_wrap() {
  return Int_val(DEREF(Cfg_numNodes(Val_unit)));
}
